package com.vgulu.server.login.service.impl;

import com.vgulu.server.common.TConstant;
import com.vgulu.server.common.exception.ErrorCode;
import com.vgulu.server.common.exception.VBaseException;
import com.vgulu.server.common.utils.OKHttpUtil;
import com.vgulu.server.common.utils.RandomStrUtil;
import com.vgulu.server.common.utils.SHACipher;
import com.vgulu.server.login.bean.LoginBean;
import com.vgulu.server.login.bean.UidBean;
import com.vgulu.server.login.bean.WxLoginRspBean;
import com.vgulu.server.login.common.UidStatus;
import com.vgulu.server.login.repository.entity.QqUser;
import com.vgulu.server.login.repository.entity.RegisterUser;
import com.vgulu.server.login.repository.entity.Uid;
import com.vgulu.server.login.repository.entity.WxUser;
import com.vgulu.server.login.repository.mapper.QqUserMapper;
import com.vgulu.server.login.repository.mapper.RegisterUserMapper;
import com.vgulu.server.login.repository.mapper.UidMapper;
import com.vgulu.server.login.repository.mapper.WxUserMapper;
import com.vgulu.server.login.service.TokenService;
import com.vgulu.server.login.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;

/**
 * Created by wangchunsee on 16/10/4.
 */
@Service
public class UserServiceImpl implements UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    UidMapper uidMapper;
    @Autowired
    QqUserMapper qqUserMapper;

    @Autowired
    WxUserMapper wxUserMapper;

    @Autowired
    RegisterUserMapper registerUserMapper;

    @Autowired
    TokenService tokenService;

    public Uid checkToken(String token) {
        Uid uid = tokenService.tokenVerify(token);
        return uid;
    }

    public LoginBean qqLogin(String appId, String openId, String accessToken,String channel) {
        QqUser qqQuery = new QqUser();
        qqQuery.setOpenId(openId);
        qqQuery.setAppId(appId);
        QqUser one = qqUserMapper.selectOne(qqQuery,QqUserMapper.SELECT_BY_OPEN_ID);
        Uid uid=null;
        if (one==null){
            Uid insertUb = addOneUid(UidStatus.OK);
            one=new QqUser();
            one.setUid(insertUb.getUid());
            one.setOpenId(openId);
            one.setAppId(appId);
            one.setToken(accessToken);
            qqUserMapper.insertSelective(one);
            uid=uidMapper.selectByPrimaryKey(one.getUid());
        }else {
            uid=uidMapper.selectByPrimaryKey(one.getUid());
            one.setToken(accessToken);
            qqUserMapper.updateByPrimaryKeySelective(one);
        }
        return tokenService.setToken(uid,appId,channel);
    }

    public LoginBean emailRegister(String appId, String email, String pwd,String channel) {
        RegisterUser query = new RegisterUser();
        query.setEmail(email);
        RegisterUser user = registerUserMapper.selectOne(query);
        if (user!=null){
            throw VBaseException.EmailExistException;
        }
        Uid uid = addOneUid(UidStatus.NotCertify);
        String salt = RandomStrUtil.getRandLetterAndNumStr(10);
        String saltPwd = SHACipher.encryptSHA256(pwd,salt);
        RegisterUser insert = new RegisterUser();
        insert.setEmailVerify((byte)0);
        insert.setPassword(saltPwd);
        insert.setSalt(salt);
        insert.setEmail(email);
        insert.setUid(uid.getUid());
        registerUserMapper.insertSelective(insert);
        //TODO 发送验证邮件
        return tokenService.setToken(uid,appId,channel);
    }

    public LoginBean emailLogin(String appId, String email, String pwd,String channel) {
        RegisterUser query = new RegisterUser();
        query.setEmail(email);
        RegisterUser user = registerUserMapper.selectOne(query);
        if (user==null){
            throw VBaseException.EmailNotRegisterException;
        }
        String saltPwd = SHACipher.encryptSHA256(pwd,user.getSalt());
        if (!saltPwd.equals(user.getPassword())){
            throw VBaseException.PasswordErrorException;
        }
        Uid uid = uidMapper.selectByPrimaryKey(user.getUid());
        if (uid==null){
            logger.error("Uid not exist, email:"+email);
            throw VBaseException.ServiceException;
        }
        return tokenService.setToken(uid,appId,channel);
    }

    public void emailResetPwd(String appId, String email) {
        return ;
    }

    public LoginBean modifyPwd(String appId, String token, String oldPwd, String newPwd,String channel) {
        Uid uid=tokenService.tokenVerify(token);
        RegisterUser user = registerUserMapper.selectByPrimaryKey(uid.getUid());
        if (user==null){
            throw VBaseException.EmailNotRegisterException;
        }
        String saltPwd = SHACipher.encryptSHA256(oldPwd,user.getSalt());
        if (!saltPwd.equals(user.getPassword())){
            throw VBaseException.PasswordErrorException;
        }
        String salt = RandomStrUtil.getRandLetterAndNumStr(10);
        String nPwd = SHACipher.encryptSHA256(newPwd,salt);
        RegisterUser insert = new RegisterUser();
        insert.setPassword(nPwd);
        insert.setSalt(salt);
        insert.setUid(uid.getUid());
        registerUserMapper.updateByPrimaryKeySelective(insert);
        //TODO 清空token
        return tokenService.setToken(uid,appId,channel);
    }

    public LoginBean mobileRegister(String appId, String phone, String pwd, String smsCode, String channel){
        RegisterUser query = new RegisterUser();
        query.setMobile(phone);
        RegisterUser user = registerUserMapper.selectOne(query);
        if (user!=null){
            throw VBaseException.MobileExistException;
        }
        //TODO 校验验证码
        Uid uid = addOneUid(UidStatus.NotCertify);
        String salt = RandomStrUtil.getRandLetterAndNumStr(10);
        String saltPwd = SHACipher.encryptSHA256(pwd,salt);
        RegisterUser insert = new RegisterUser();
        insert.setMobileVerify((byte)1);
        insert.setPassword(saltPwd);
        insert.setSalt(salt);
        insert.setMobile(phone);
        insert.setUid(uid.getUid());
        registerUserMapper.insertSelective(insert);
        return tokenService.setToken(uid,appId,channel);
    }

    public LoginBean mobileLogin(String appId, String mobile, String pwd, String channel){
        RegisterUser query = new RegisterUser();
        query.setMobile(mobile);
        RegisterUser user = registerUserMapper.selectOne(query);
        if (user==null){
            throw VBaseException.MobileNotRegisterException;
        }
        String saltPwd = SHACipher.encryptSHA256(pwd,user.getSalt());
        if (!saltPwd.equals(user.getPassword())){
            throw VBaseException.PasswordErrorException;
        }
        Uid uid = uidMapper.selectByPrimaryKey(user.getUid());
        if (uid==null){
            logger.error("Uid not exist, mobile:"+mobile);
            throw VBaseException.ServiceException;
        }
        return tokenService.setToken(uid,appId,channel);
    }

    @Override
    public LoginBean wxlogin(String appId, String code) {

        String[] wxIdAndSecret = getWxAppIdAndSecret(appId);
        if (wxIdAndSecret==null){
            throw ErrorCode.APP_ID_INVALID.toException();
    }
        String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",wxIdAndSecret[0],wxIdAndSecret[1],code);
        String str = null;
        try {
            str = OKHttpUtil.get(url);
        } catch (IOException e) {
            throw  ErrorCode.WX_LOGIN_API_ERROR.toException();
        }
        WxLoginRspBean rsp = null;
        if (!StringUtils.isEmpty(str)){
            rsp = TConstant.gson.fromJson(str, WxLoginRspBean.class);
            if(rsp==null||StringUtils.isEmpty(rsp.getOpenid())){
               throw  ErrorCode.WX_CODE_INVALID.toException();
            }
        }else {
            throw  ErrorCode.WX_LOGIN_API_ERROR.toException();
        }
        String openId = rsp.getOpenid();
        String accessToken=rsp.getSessionKey();
        WxUser qqQuery = new WxUser();
        qqQuery.setOpenId(openId);
        qqQuery.setAppId(appId);
        WxUser one = wxUserMapper.selectOne(qqQuery,WxUserMapper.SELECT_BY_OPEN_ID);
        Uid uid=null;
        if (one==null){
            Uid insertUb = addOneUid(UidStatus.OK);
            one=new WxUser();
            one.setUid(insertUb.getUid());
            one.setOpenId(openId);
            one.setAppId(appId);
            one.setToken(accessToken);
            wxUserMapper.insertSelective(one);
            uid=uidMapper.selectByPrimaryKey(one.getUid());
        }else {
            uid=uidMapper.selectByPrimaryKey(one.getUid());
            one.setToken(accessToken);
            wxUserMapper.updateByPrimaryKeySelective(one);
        }
        return tokenService.setToken(uid,appId,"wxapp");
    }

    private String[] getWxAppIdAndSecret(String appId) {
        return new String[]{"wx0b3f5d0a71190352","a27260cb804d6b6e82f5a9e7d5d83ef8"};
    }

    private Uid addOneUid(int status){
        Uid insertUb = new Uid();
        insertUb.setStatus((byte)status);
        insertUb.setCreateTs(new Date());
        insertUb.setUpdateTs(new Date());
        uidMapper.insertSelective(insertUb);
        return insertUb;
    }
}
